package com.ideal.tools.ssh.context;



import com.ideal.service.Utils;
import com.ideal.tools.ssh.common.CommonProperties;
import com.ideal.tools.ssh.common.PropertyBox;
import com.ideal.tools.ssh.entity.ContextResult;
import com.ideal.tools.ssh.entity.LinuxMachine;
import com.ideal.tools.ssh.operation.LinuxOperation;
import com.ideal.tools.ssh.result.LinuxResult;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by CC on 2016/3/1.
 * 对于一个 前台的需求 会对应一个context
 */
public class ClusterContext {

    LinuxMachine curMachine;
    List<LinuxMachine> orignalMachineList;  //最原始的machinelist 或者说全部的machine
    List<LinuxMachine> machineList ;        //每次操作的时候的machine 会一直变化
    CommonProperties commonProperties;
    List<LinuxResult> resultList;//这个会记录所有的结果

    Map<String,LinuxOperation> onlyOnceMap;//这里记录只能运行一次的 操作

    List<String> contextSteps;  //用来记录这个 整体的所有操作
    String curStep;
    ContextResult contextResult;
    private static Logger logger = LoggerFactory.getLogger(ClusterContext.class);
    public ClusterContext(CommonProperties commonProperties){
        this.commonProperties = commonProperties;
        this.machineList = new ArrayList<LinuxMachine>();
        this.orignalMachineList = new ArrayList<LinuxMachine>();
        this.resultList = new ArrayList<LinuxResult>();
        this.contextSteps = new ArrayList<String>();
    }

    public ClusterContext(Map<String,Object> arguments){
        //放入共有参数
        commonProperties = new CommonProperties(PropertyBox.getAllVals());
        if(arguments!=null) {
            for (Map.Entry<String, Object> entry : arguments.entrySet()) {
                if (entry.getValue() instanceof String) {
                    commonProperties.setArgument(entry.getKey(), ((String) entry.getValue()));
                } else {
                    commonProperties.setObjParamter(entry.getKey(), entry.getValue());
                }
            }
        }
        //获取原始机器列表
        this.orignalMachineList = Utils.getTotalMachineInfoList();

        this.resultList = new ArrayList<LinuxResult>();
        this.contextSteps = new ArrayList<String>();
        this.machineList = new ArrayList<LinuxMachine>();
        this.contextResult = new ContextResult();

    }

    public LinuxMachine getCurMachine() {
        return curMachine;
    }

    public List<LinuxMachine> getMachineList() {
        return machineList;
    }

    public void setMachineList(List<LinuxMachine> machineList ){
        this.machineList=machineList;

        //在机器中 放入context
        for(LinuxMachine machine:machineList){
            machine.initLinuxContext(this);
        }
    }

    public void setOriginalList(List<LinuxMachine> orignalMachineList){
        this.orignalMachineList=orignalMachineList;
    }

    public List<LinuxMachine> getOriginalList(){
        return this.orignalMachineList;
    }

    public void setCurStep(String curStep){
        if(StringUtils.isBlank(curStep)){
            curStep="Clarm_"+System.currentTimeMillis();
        }
        this.curStep=curStep;
        contextSteps.add(curStep);
    }

    public CommonProperties getCommonProperties() {
        return commonProperties;
    }

    public void setCommonProperties(CommonProperties commonProperties) {
        this.commonProperties = commonProperties;
    }

    /**
     * 在context 中加入机器
     * @param ip
     * @param userName
     * @param passWD
     * @param pubKey
     * @param operationList
     * @return
     */
    public ClusterContext initMachine(String ip,String userName, String passWD,
                                    String pubKey,List<LinuxOperation> operationList){
        LinuxMachine linuxMachine = new LinuxMachine().initIP(ip).initPubKey(pubKey).
                initLoginName(userName).initPassWord(passWD).initOperations(operationList).
                initLinuxContext(this);

        //装入 machineList
        machineList.add(linuxMachine);
        return this;
    }


    public void doTheThing(){
        /**遍历所有的机器 完成每一个机器 的操作 **/
        if(contextResult==null){
            contextResult =new ContextResult();
        }
        for(LinuxMachine machine:machineList){
            machine.initLinuxContext(this);
            //赋值当前机器
            curMachine = machine;
            //执行
            curMachine.doOperation();
            //放入最终结果集
            contextResult.setConextResult(curStep,curMachine.getResult());
        }

        /**这个需要在最后的时候清空机器的operation 和 roletype**/
        for(LinuxMachine machine:machineList){
          machine.clearMachine();
        }
    }

    public Map<String,List<LinuxResult>>  getProcessResult(){
        return contextResult.getAllResult();
    }

    public ContextResult getContextResult(){
        return contextResult;
    }

    public void printResult(){
        for(LinuxMachine machine:machineList){
            List<LinuxResult> results=machine.getResult();
            for(LinuxResult result:results){
                logger.info("std:"+result.getStdOut());
                logger.info("err:"+result.getErrOut());
                logger.info("exception:"+result.getException());
                logger.info("node:"+result.getNote());
                logger.info("exitCode:"+result.getExitCode());
                logger.info("cmd:" +result.getCmd());

            }
        }
    }

    public void sysOutResult(){
        for(Map.Entry<String,List<LinuxResult>> entry:contextResult.getAllResult().entrySet() ){
            for(LinuxResult result : entry.getValue()) {
                System.out.println("==========start==========");
                System.out.println("std:" + result.getStdOut());
                System.out.println("err:" + result.getErrOut());
                System.out.println("exception:" + result.getException());
                System.out.println("node:" + result.getNote());
                System.out.println("exitCode:" + result.getExitCode());
                System.out.println("cmd:" + result.getCmd());
                System.out.println("===========end=========");
            }
        }
    }




    public void setOnlyOneceOperation(LinuxMachine linuxMachine,LinuxOperation operation){
        String key=operation.getLinuxOperationID();
        if(onlyOnceMap==null){
            onlyOnceMap=new HashMap<String, LinuxOperation>();
        }
        if(onlyOnceMap.get(key)==null) {
            onlyOnceMap.put(key, operation);
        }
    }


    /**
     * 这里 这个判断是否 只需执行一次
     * 只有执行 并且是 执行成功了才行
     * @param linuxMachine
     * @param operation
     * @return
     */
    public boolean isOnlyOnceOperation(LinuxMachine linuxMachine,LinuxOperation operation){
        if(onlyOnceMap==null)return false;
        String key=operation.getLinuxOperationID();
        LinuxOperation oldOperation = onlyOnceMap.get(key);
        //为null 表着不是一个 只执行一次的操作
        if (oldOperation==null)return false;

        //只有执行成功的才能继续
        if(oldOperation.getExeResult()!=null&&
                oldOperation.getExeResult().getExitCode()==LinuxResult.DEFAULT_SUCCESS_CODE) {
            return true;
        }

        return false;
    }
}
